﻿using System;
using System.Collections.Generic;
using Ivory.Libs;
using Microsoft.Xna.Framework;
using Jitter;
using Jitter.LinearMath;
using Ivory;

namespace Crystal.Libs
{
    public class SelectionChangedEventArgs : EventArgs
    {
        public ISelectable3D Selected;
        
        public SelectionChangedEventArgs(ISelectable3D selected)
        {
            this.Selected = selected;
        }
    }

    public static class SelectionEngine
    {
        private static List<ISelectable3D> _SelectablesList;
        
        public static event EventHandler<SelectionChangedEventArgs> SelectionChanged;
        public static event EventHandler<SelectionChangedEventArgs> HoverChanged;

        public static void Create()
        {
            _SelectablesList = new List<ISelectable3D>();
        }
        public static void Clear()
        {
            _SelectablesList = new List<ISelectable3D>();
        }

        public static void Register(ISelectable3D selectable)
        {
            if (_SelectablesList == null)
                _SelectablesList = new List<ISelectable3D>();

            _SelectablesList.Add(selectable);
        }
        public static void RegisterRange(IEnumerable<ISelectable3D> selectables)
        {
            if (_SelectablesList == null)
                _SelectablesList = new List<ISelectable3D>();

            _SelectablesList.AddRange(selectables);
        }

        public static Vector3 RayTo(Game game, Camera camera, InputControl input)
        {
            float x = input.MouseVect.X;
            float y = input.MouseVect.Y;

            Vector3 nearSource = new Vector3(x, y, 0);
            Vector3 farSource = new Vector3(x, y, 1);

            Matrix world = Matrix.Identity;

            Vector3 nearPoint = game.GraphicsDevice.Viewport.Unproject(nearSource, camera.Projection, camera.View, world);
            Vector3 farPoint = game.GraphicsDevice.Viewport.Unproject(farSource, camera.Projection, camera.View, world);

            Vector3 direction = farPoint - nearPoint;
            return direction;
        }

        public static void SolveSelection(Game game, InputControl input)
        {   
            foreach (ISelectable3D selectable in _SelectablesList)
            {
                JVector ray = Conversion.ConvertVect(RayTo(game, Globals.GameCamera, input));
                JVector normal;
                float fraction;
                bool result = Globals.GameWorld.CollisionSystem.Raycast(selectable.Body, Conversion.ConvertVect(Globals.GameCamera.CameraPosition), ray, out normal, out fraction);

                if (result)
                {
                    if (HoverChanged != null)
                        HoverChanged(null, new SelectionChangedEventArgs(selectable));

                    if (input.IsLeftClick())
                    {
                        if (SelectionChanged != null)
                            SelectionChanged(null, new SelectionChangedEventArgs(selectable));
                    }
                }
            }
        }
    }
}
